<template>
  <div class="date-panel">
    <component ref="panel" :is="panel" @pick="pick"></component>
  </div>
</template>
<script>
import DatePanel from './date-picker/src/panel/date'
import DateRangePanel from './date-picker/src/panel/date-range'
import MonthRangePanel from './date-picker/src/panel/month-range'
import { formatDate, getWeekNumber, isDateObject, parseDate } from 'element-ui/src/utils/date-util'

const DEFAULT_FORMATS = {
  date: 'yyyy-MM-dd',
  month: 'yyyy-MM',
  months: 'yyyy-MM',
  datetime: 'yyyy-MM-dd HH:mm:ss',
  time: 'HH:mm:ss',
  week: 'yyyywWW',
  timerange: 'HH:mm:ss',
  daterange: 'yyyy-MM-dd',
  monthrange: 'yyyy-MM',
  datetimerange: 'yyyy-MM-dd HH:mm:ss',
  year: 'yyyy',
  years: 'yyyy'
}
const DATE_FORMATTER = function (value, format) {
  if (format === 'timestamp') return value.getTime()
  return formatDate(value, format)
}
const DATE_PARSER = function (text, format) {
  if (format === 'timestamp') return new Date(Number(text))
  return parseDate(text, format)
}
const RANGE_FORMATTER = function (value, format) {
  if (Array.isArray(value) && value.length === 2) {
    const start = value[0]
    const end = value[1]

    if (start && end) {
      return [DATE_FORMATTER(start, format), DATE_FORMATTER(end, format)]
    }
  }
  return ''
}
const RANGE_PARSER = function (array, format, separator) {
  if (!Array.isArray(array)) {
    array = array.split(separator)
  }
  if (array.length === 2) {
    const range1 = array[0]
    const range2 = array[1]

    return [DATE_PARSER(range1, format), DATE_PARSER(range2, format)]
  }
  return []
}
const TYPE_VALUE_RESOLVER_MAP = {
  default: {
    formatter(value) {
      if (!value) return ''
      return '' + value
    },
    parser(text) {
      if (text === undefined || text === '') return null
      return text
    }
  },
  week: {
    formatter(value, format) {
      let week = getWeekNumber(value)
      let month = value.getMonth()
      const trueDate = new Date(value)
      if (week === 1 && month === 11) {
        trueDate.setHours(0, 0, 0, 0)
        trueDate.setDate(trueDate.getDate() + 3 - (trueDate.getDay() + 6) % 7)
      }
      let date = formatDate(trueDate, format)

      date = /WW/.test(date)
          ? date.replace(/WW/, week < 10 ? '0' + week : week)
          : date.replace(/W/, week)
      return date
    },
    parser(text, format) {
      // parse as if a normal date
      return TYPE_VALUE_RESOLVER_MAP.date.parser(text, format)
    }
  },
  date: {
    formatter: DATE_FORMATTER,
    parser: DATE_PARSER
  },
  datetime: {
    formatter: DATE_FORMATTER,
    parser: DATE_PARSER
  },
  daterange: {
    formatter: RANGE_FORMATTER,
    parser: RANGE_PARSER
  },
  monthrange: {
    formatter: RANGE_FORMATTER,
    parser: RANGE_PARSER
  },
  datetimerange: {
    formatter: RANGE_FORMATTER,
    parser: RANGE_PARSER
  },
  timerange: {
    formatter: RANGE_FORMATTER,
    parser: RANGE_PARSER
  },
  time: {
    formatter: DATE_FORMATTER,
    parser: DATE_PARSER
  },
  month: {
    formatter: DATE_FORMATTER,
    parser: DATE_PARSER
  },
  year: {
    formatter: DATE_FORMATTER,
    parser: DATE_PARSER
  },
  number: {
    formatter(value) {
      if (!value) return ''
      return '' + value
    },
    parser(text) {
      let result = Number(text)

      if (!isNaN(text)) {
        return result
      } else {
        return null
      }
    }
  },
  dates: {
    formatter(value, format) {
      return value.map(date => DATE_FORMATTER(date, format))
    },
    parser(value, format) {
      return (typeof value === 'string' ? value.split(', ') : value)
          .map(date => date instanceof Date ? date : DATE_PARSER(date, format))
    }
  },
  months: {
    formatter(value, format) {
      return value.map(date => DATE_FORMATTER(date, format))
    },
    parser(value, format) {
      return (typeof value === 'string' ? value.split(', ') : value)
          .map(date => date instanceof Date ? date : DATE_PARSER(date, format))
    }
  },
  years: {
    formatter(value, format) {
      return value.map(date => DATE_FORMATTER(date, format))
    },
    parser(value, format) {
      return (typeof value === 'string' ? value.split(', ') : value)
          .map(date => date instanceof Date ? date : DATE_PARSER(date, format))
    }
  }
}
const formatAsFormatAndType = (value, customFormat, type) => {
  if (!value) return null
  const formatter = (
      TYPE_VALUE_RESOLVER_MAP[type] ||
      TYPE_VALUE_RESOLVER_MAP['default']
  ).formatter
  const format = customFormat || DEFAULT_FORMATS[type]
  return formatter(value, format)
}

export default {
  name: 'date-panel',
  props: {
    value: {},
    format: String,
    valueFormat: String,
    showTime: {
      default: false,
      type: Boolean
    },
    type: {
      default: 'date' // daterange, monthrange
    }
  },
  components: {
    DatePanel,
    DateRangePanel,
    MonthRangePanel
  },
  computed: {
    panel() {
      const map = {
        date: DatePanel,
        daterange: DateRangePanel,
        monthrange: MonthRangePanel
      }
      return map[this.type]
    }
  },
  mounted() {
    // 日期
    this.$refs.panel.value = this.value
    // 是否包含时间
    this.$refs.panel.showTime = this.showTime
    // visible控制是否显示日期面板
    this.$refs.panel.visible = true
  },
  methods: {
    pick(date) {
      console.log('date-->', date)
      this.$refs.panel.value = date
      this.$refs.panel?.resetView()
      this.$emit('input', this.formatToValue(date))
    },
    formatToValue(date) {
      const isFormattable = isDateObject(date) || (Array.isArray(date) && date.every(isDateObject))
      if (this.valueFormat && isFormattable) {
        return formatAsFormatAndType(date, this.valueFormat, this.type)
      } else {
        return date
      }
    }
  }
}
</script>
<style lang="scss" scoped>
/* 原生CSS的深度选择器<<< */
.date-panel {
  ::v-deep {
    .el-picker-panel__footer {
      /* 隐藏.el-picker-panel的底部确定按钮 */
      display: none !important;
    }

    .el-picker-panel {
      box-shadow: none;
      /* border: 0; */
    }
  }
}

</style>

